By: Allyson Lynch

In [1]:
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import math
from scipy import stats

Plot the popularity distribution by count, cumulative probability, and log probability.

In [2]:
def popularity_plot(class_list, pareto_marker=False, log_plot=False, log_plot_reg=False, file=False):
    """takes a file with smiles strings and popularity calculation information for each category and the optional argument for a log plot and returns distribution plots"""
    pareto_df = pd.read_table('Outputs/02 Popularity Files/pareto_split.tsv')
    for molecule in class_list: 
        #make a dataframe per molcule (skip smiles)
        smiles_df = pd.read_table('Outputs/02 Popularity Files/'+molecule+'_popularity.tsv')
        smiles_df = smiles_df[smiles_df["number_" + molecule]>0] #remove if absent
        graph_df = smiles_df.sort_values(by=["number_" + molecule]) #sort by count in increasing order
        split_df = pareto_df[pareto_df['molecule']=='number_'+molecule]
        #distribution plot
        if file:
            save_df = graph_df.loc[:, ['smiles', 'rank', "number_" + molecule]] #only include smiles, rank, and number
            save_df.to_csv("Outputs/04 Graphs/popularity_plot/" + molecule + "distributionplot.tsv", sep='\t') #save as tsv
        plt.figure() #seperate graphs
        plot = sns.regplot(x= 'rank', y= "number_" + molecule, data= graph_df, fit_reg=False)
        plot.set_title(molecule) #scatterplot of cumulative probabilities
        fig = plot.get_figure()
        fig.savefig("Outputs/04 Graphs/popularity_plot/"+molecule+"_distributionplot.svg")
        #cumulative probability
        if file:
            save_df = graph_df.loc[:, ['smiles', molecule+"_proportion", molecule+"_rcumulativeprob"]] #only include smiles, rank, number, and cumulative count
            save_df.to_csv("Outputs/04 Graphs/popularity_plot/" + molecule + "cumprobplot.tsv", sep='\t') #save as tsv
        plt.figure() #seperate graphs
        plot = sns.regplot(x= molecule+"_proportion", y= molecule+"_rcumulativeprob", data=graph_df, fit_reg=False)
        if pareto_marker:
            p=sns.regplot(x='percent_structures', y='percent_amines', data= split_df, fit_reg=False, marker="x", color='r')
            p.text(x=split_df['percent_structures']+.03, y=split_df['percent_amines']-.03, s='Pareto split', fontsize=10, fontdict={'color':'r'})
        plot.set_title(molecule) #scatterplot of amounts
        fig = plot.get_figure()
        fig.savefig("Outputs/04 Graphs/popularity_plot/"+molecule+"_cumprobplot.svg")
        #log graph
        if log_plot:
            probability_df = graph_df.sort_values(by=[molecule + "_probability"], ascending=False) #sort by probability in decreasing order
            x_values = [math.log(i, 10) for i in range(1, len(probability_df['smiles'].tolist())+1)] #list of rank
            y_values = [math.log(i, 10) if i!=0 else 0 for i in probability_df[molecule + "_probability"].tolist()] #list of number
            log_df = pd.DataFrame({'log rank':x_values, 'log probability':y_values}) #create dataframe
            plt.figure()
            if log_plot_reg:
                plot = sns.regplot(x= 'log rank', y= 'log probability', data= log_df, fit_reg=True)
                slope, intercept, r_value, p_value, std_err = stats.linregress(log_df['log rank'],log_df['log probability'])
                print("y="+str(slope)+"x+"+str(intercept)+" r2="+str(r_value**2))
            else:
                plot = sns.regplot(x= 'log rank', y= 'log probability', data= log_df, fit_reg=False)
            plot.set_title("log "+molecule) #scatterplot
            fig = plot.get_figure()
            fig.savefig("Outputs/04 Graphs/popularity_plot/"+molecule+"_logplot.svg")

Probability distribution of popularvsunpopular or successvsfailure for each property.

In [3]:
def pdf_graph(class_list, properties_file, outcome=False, include_absent_amines=True, file=False):
    """takes a popularity data file, properties data file, and optional parameter for including absent (-1) and returns a histogram of the probability distribution function"""
    df_properties = pd.read_table(properties_file)
    df_properties_drop = df_properties.drop(['_raw_Reaction number', '_raw_name', '_raw_SMILES', '_raw_SMILES.nosalt', '_rxn_Synthesis_Method', '_raw_Notes', '_out_Outcome'], axis=1)
    if outcome:
        df_popularity = pd.read_table("Outputs/03 Outcomes/triangle_outcomestats.tsv")
        popularity_properties = pd.merge(df_popularity, df_properties, left_on='Smiles', right_on='Smiles', how='right') #merge popularity and properties by smiles
    else:
        df_popularity = pd.read_table("Outputs/02 Popularity Files/amine_popularity.tsv")
        popularity_properties = pd.merge(df_popularity, df_properties, left_on='smiles', right_on='Smiles', how='right') #merge popularity and properties by smiles
        popularity_properties[["metalborates_popular"]] = popularity_properties[["metalborates_popular"]].fillna(value=-1) #mark absent
    #make a list per molecule...
    for molecule in class_list:
        #make popular and unpopular data frames
        if outcome:
            popular_df = popularity_properties.loc[popularity_properties['OUT_anySuccess?']==True] #success dataframe
            unpopular_df = popularity_properties.loc[popularity_properties['OUT_anySuccess?']==False] #fail dataframe
        else:
            popular_df = popularity_properties.loc[popularity_properties[molecule+"_popular"]==1] #popular dataframe
            if include_absent_amines: 
                unpopular_df = popularity_properties.loc[popularity_properties[molecule+"_popular"] <= 0] #unpopular + absent dataframe
            else:
                unpopular_df = popularity_properties.loc[popularity_properties[molecule+"_popular"]==0] #unpopular dataframe
        #...of the pdfs for each property
        for prop in df_properties.columns[1:-1]:
            #make lists of property
            discrete=False #intialize
            popular = popular_df[prop].dropna().tolist()
            unpopular = unpopular_df[prop].dropna().tolist()
            if len(popular)>0: 
                if type(popular[0])==int:
                    discrete=True
                    if discrete:
                        if outcome:
                            graph_df = pd.DataFrame(columns=[prop, 'Probability', 'outcome'])
                        else:
                            graph_df = pd.DataFrame(columns=[prop, 'Probability', 'popularity'])
                        short = list(set(popular))
                        graph_df[prop] = short + short
                        if outcome:
                            graph_df['outcome'] = ['success' for i in range(len(short))] +  ['failure' for i in range(len(short))]
                        else:
                            if include_absent_amines:
                                graph_df['popularity'] = ['popular' for i in range(len(short))] +  ['notpopular' for i in range(len(short))] 
                            else:
                                graph_df['popularity'] = ['popular' for i in range(len(short))] +  ['unpopular' for i in range(len(short))]
                        graph_df['Probability'] = [popular.count(i)/len(popular) for i in short] + [unpopular.count(i)/len(unpopular) for i in short]
                        name = prop.replace("/", "_")
                        if file:
                            if outcome:
                                graph_df.to_csv("Outputs/04 Graphs/pdf/"+molecule+"_"+name+"_outcomepdf.tsv", sep='\t') #save as tsv
                            else:
                                graph_df.to_csv("Outputs/04 Graphs/pdf/"+molecule+"_"+name+"_pdf.tsv", sep='\t') #save as tsv
                        plt.figure() #seperate graphs
                        if outcome:
                            plot = sns.barplot(x=prop, y='Probability', hue='outcome', data=graph_df, palette=['g','r'])
                        else:
                            plot = sns.barplot(x=prop, y='Probability', hue='popularity', data=graph_df, palette=['k','0.50'])
                        plot.set(title=prop) 
                        fig = plot.get_figure()
                        if outcome:
                            fig.savefig("Outputs/04 Graphs/pdf/"+molecule+"_"+name+"_outcomepdfplot.svg")
                        else:
                            fig.savefig("Outputs/04 Graphs/pdf/"+molecule+"_"+name+"_pdfplot.svg")
                elif type(popular[0])==float:
                    plt.figure() #seperate graphs
                    if outcome:
                        plot = sns.distplot(popular, color='g')
                        plot = sns.distplot(unpopular, color='r')
                    else:
                        plot = sns.distplot(popular, color='k')
                        plot = sns.distplot(unpopular, color='0.75')
                    plot.set(title=prop)
                    fig = plot.get_figure()
                    prop = prop.replace("/", "_")
                    if outcome:
                        fig.savefig("Outputs/04 Graphs/pdf/"+molecule+"_"+prop+"_outcomepdfplot.svg")
                    else:
                        fig.savefig("Outputs/04 Graphs/pdf/"+molecule+"_"+prop+"_pdfplot.svg")

Plot the original and triangle manipulated property distribution.

In [4]:
def property_graph(properties_file, file=False):
    """takes a popularity data file, properties data file, and optional parameter for including absent (-1) and returns a histogram of the probability distribution function"""
    df_properties = pd.read_table(properties_file, engine='python')
    df_properties_drop = df_properties.loc[:, ['Smiles', '_rxn_pH', '_raw_Amine_Mol']]
    #pH
    graph_df = pd.DataFrame(columns=['_rxn_pH', 'Probability'])
    values = df_properties['_rxn_pH'].tolist()
    short = list(set(values))
    graph_df['_rxn_pH'] = short 
    graph_df['Probability'] = [values.count(i)/len(values) for i in short]
    if file:
        graph_df.to_csv("Outputs/04 Graphs/property_graph/"+'_rxn_pH'+properties_file[20:-10]+"_barplot.tsv", sep='\t') #save as tsv
    plt.figure() #seperate graphs
    plot = sns.barplot(x='_rxn_pH', y='Probability', data=graph_df)
    plot.set(title='_rxn_pH')
    fig = plot.get_figure()
    fig.savefig("Outputs/04 Graphs/property_graph/"+'_rxn_pH'+properties_file[20:-10]+"_barplot.svg")
    #amine mols
    values = df_properties['_raw_Amine_Mol'].tolist()
    plt.figure()
    plot = sns.distplot(values)
    plot.set(title='_raw_Amine_Mol')
    fig = plot.get_figure()
    fig.savefig("Outputs/04 Graphs/property_graph/"+'_raw_Amine_Mol'+properties_file[20:-10]+"_barplot.svg")
In [5]:
def graphs(class_list, properties_files, pareto_marker=False, log_plot=False, log_plot_reg=False, include_absent_amines=True, outcome=False, file=False):
    popularity_plot(class_list, pareto_marker, log_plot, log_plot_reg, file)
    pdf_graph(class_list, properties_files[0], outcome, include_absent_amines, file)
    for f in properties_files:
        property_graph(f, file)

graphs(["metaloxides", "metalborates"], ["Outputs/03 Outcomes/triangle_clean.tsv", "Outputs/03 Outcomes/human_clean.tsv"], log_plot=True, outcome=True, file=True)
graphs(["metaloxides", "metalborates"], ["Outputs/03 Outcomes/triangle_clean.tsv", "Outputs/03 Outcomes/human_clean.tsv"], log_plot=True, file=True)
/homes/aalynch/.local/lib/python3.5/site-packages/matplotlib/axes/_axes.py:6462: UserWarning: The 'normed' kwarg is deprecated, and has been replaced by the 'density' kwarg.
  warnings.warn("The 'normed' kwarg is deprecated, and has been "
/homes/aalynch/.local/lib/python3.5/site-packages/matplotlib/pyplot.py:537: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
  max_open_warning, RuntimeWarning)
/usr/local/lib/python3.5/dist-packages/statsmodels/nonparametric/kde.py:494: RuntimeWarning: invalid value encountered in true_divide
  binned = fast_linbin(X,a,b,gridsize)/(delta*nobs)
/usr/local/lib/python3.5/dist-packages/statsmodels/nonparametric/kdetools.py:34: RuntimeWarning: invalid value encountered in double_scalars
  FAC1 = 2*(np.pi*bw/RANGE)**2
/homes/aalynch/.local/lib/python3.5/site-packages/numpy/core/_methods.py:26: RuntimeWarning: invalid value encountered in reduce
  return umr_maximum(a, axis, None, out, keepdims)
/homes/aalynch/.local/lib/python3.5/site-packages/numpy/lib/function_base.py:838: RuntimeWarning: invalid value encountered in true_divide
  return n/db/n.sum(), bin_edges